package cn.lingyangwl.agile.system.manager;

import cn.lingyangwl.agile.common.core.exception.enums.GlobalErrorEnum;
import cn.lingyangwl.agile.model.constants.TenantCons;
import cn.lingyangwl.agile.model.enums.BoolEnum;
import cn.lingyangwl.agile.model.module.tenant.TenantContext;
import cn.lingyangwl.agile.system.mapper.SysRoleMapper;
import cn.lingyangwl.agile.system.mapper.SysRoleMenuRelMapper;
import cn.lingyangwl.agile.system.mapper.SysUserRoleMapper;
import cn.lingyangwl.agile.system.model.entity.SysRole;
import cn.lingyangwl.agile.system.model.entity.SysRoleMenu;
import cn.lingyangwl.agile.system.model.entity.SysUserRole;
import cn.lingyangwl.framework.tool.core.CollectionUtils;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author shenguangyang
 */
@Slf4j
@Component
public class SysRoleManager extends ServiceImpl<SysRoleMapper, SysRole> {
    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private SysRoleMenuRelMapper roleMenuMapper;

    /**
     * 通过角色ID删除角色
     *
     * @param roleId 角色ID
     * @return 结果
     */
    public boolean deleteById(Long roleId) {
        LambdaUpdateWrapper<SysRole> wrapper = Wrappers.<SysRole>lambdaUpdate()
                .set(SysRole::getDeleted, BoolEnum.FALSE.getCode())
                .eq(SysRole::getId, roleId);
        return this.update(null, wrapper);
    }

    public boolean deleteByIds(List<Long> roleIds) {
        return this.removeByIds(roleIds);
    }

    @Transactional
    public void deleteRoleByRoleIds(List<Long> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return;
        }
        LambdaQueryWrapper<SysRole> lqw = SysRole.lqw().in(SysRole::getId, roleIds);
        
        if (!this.remove(lqw)) {
            throw new BizException(GlobalErrorEnum.OPERATION_FAIL_DELETE.getCode(), "删除角色失败");
        }

        // 删除角色和用户
        userRoleMapper.delete(SysUserRole.lqw().in(SysUserRole::getRoleId, roleIds));

        // 删除角色和菜单
        roleMenuMapper.delete(SysRoleMenu.lqw().in(SysRoleMenu::getRoleId, roleIds));
    }

    public List<SysRole> checkRole(List<Long> roleIdList) {
        if (CollectionUtils.isEmpty(roleIdList)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<SysRole> lqw = SysRole.lqw()
                .in(CollectionUtils.isNotEmpty(roleIdList), SysRole::getId, roleIdList);
        List<SysRole> list = this.list(lqw);
        if (list.size() != roleIdList.size()) {
            throw new BizException("添加的角色中有不存在的角色");
        }
        return list;
    }

    /**
     * 获取角色
     * @param userIds 用户ids
     * @return key = userId
     */
    public Map<Long, List<SysRole>> listRoleByUserIds(List<Long> userIds) {
        Map<Long, List<SysRole>> respMap = new HashMap<>();

        if (CollectionUtils.isEmpty(userIds)) {
            return Collections.emptyMap();
        }
        // 查询角色
        LambdaQueryWrapper<SysUserRole> lqw = SysUserRole.lqw().in(SysUserRole::getUserId, userIds);
        List<SysUserRole> userRoleList = userRoleMapper.selectList(lqw);

        List<Long> roleIds = userRoleMapper.selectList(lqw).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(roleIds)) {
            return Collections.emptyMap();
        }

        List<SysRole> roleList = this.listByIds(roleIds);
        Map<Long, SysRole> roleMap = roleList.stream().collect(Collectors.toMap(SysRole::getId, Function.identity()));

        userRoleList.forEach(e -> {
            SysRole role = roleMap.get(e.getRoleId());
            if (Objects.isNull(role)) {
                return;
            }
            List<SysRole> list = respMap.computeIfAbsent(e.getUserId(), key -> new ArrayList<>());
            list.add(role);

        });
        return respMap;
    }

    public SysRole getByName(String name) {
        return this.getOne(SysRole.lqw().eq(SysRole::getRoleName, name));
    }

    public SysRole getByCode(String code) {
        return this.getOne(SysRole.lqw().eq(SysRole::getRoleCode, code));
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void deleteAllRole() {
        String tenantId = TenantContext.get().getTenantId();
        if (TenantCons.SYSTEM_TENANT_ID.equals(tenantId) || StringUtils.isEmpty(tenantId)) {
            log.warn("正常删除非法租户 {} 下的用户, 已拦截", tenantId);
            return;
        }
        LambdaQueryWrapper<SysRole> lqw = SysRole.lqw();
        this.remove(lqw);

        // 删除关系
        userRoleMapper.delete(SysUserRole.lqw());
        
        // 删除角色和菜单关系
        roleMenuMapper.delete(SysRoleMenu.lqw());
    }
}
